package net.diaowen.dwsurvey.service.impl;



import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.LockOptions;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import net.diaowen.common.base.entity.User;
import net.diaowen.common.base.entity.WcUserDetail;
import net.diaowen.common.base.service.AccountManager;
import net.diaowen.common.plugs.page.Page;
import net.diaowen.common.plugs.page.PropertyFilter;
import net.diaowen.common.service.BaseServiceImpl;
import net.diaowen.common.utils.Arithmetic;
import net.diaowen.common.utils.SystemUtils;
import net.diaowen.dwsurvey.dao.LotteryPrizeArithmeticDao;
import net.diaowen.dwsurvey.dao.LotteryPrizeDao;
import net.diaowen.dwsurvey.dao.LotteryPrizeDetailDao;
import net.diaowen.dwsurvey.dao.LotteryPrizeStatusDao;
import net.diaowen.dwsurvey.dao.LotteryUserDao;
import net.diaowen.dwsurvey.dao.LotteryUserDetailDao;
import net.diaowen.dwsurvey.dao.PrizeTypeDao;
import net.diaowen.dwsurvey.dao.StudentLotteryDao;
import net.diaowen.dwsurvey.dao.SurveyAnswerDao;
import net.diaowen.dwsurvey.entity.LotteryActivity;
import net.diaowen.dwsurvey.entity.LotteryPrize;
import net.diaowen.dwsurvey.entity.LotteryPrizeArithmetic;
import net.diaowen.dwsurvey.entity.LotteryPrizeDetail;
import net.diaowen.dwsurvey.entity.LotteryPrizeStatus;
import net.diaowen.dwsurvey.entity.LotteryUser;
import net.diaowen.dwsurvey.entity.LotteryUserDetail;
import net.diaowen.dwsurvey.entity.Prize;
import net.diaowen.dwsurvey.entity.PrizeType;
import net.diaowen.dwsurvey.entity.StudentLottery;
import net.diaowen.dwsurvey.entity.StudentSurvey;
import net.diaowen.dwsurvey.entity.SurveyAnswer;
import net.diaowen.dwsurvey.service.LotteryActivityManager;
import net.diaowen.dwsurvey.service.LotteryPrizeManager;
import net.diaowen.dwsurvey.service.LotteryUserManager;
import net.diaowen.dwsurvey.service.WechatManager;

@Service
public class LotteryUserManagerImpl extends BaseServiceImpl<LotteryUser, String> implements  LotteryUserManager {


	@Autowired
	private AccountManager accountManager;

	@Autowired
	private StudentLotteryDao studentLotteryDao;

	@Autowired
	private LotteryUserDetailDao lotteryUserDetailDao;

	@Autowired
	private LotteryUserDao lotteryUserDao;

	@Autowired
	private LotteryPrizeStatusDao lotteryPrizeStatusDao;

	@Autowired
	private WechatManager wechatManager;

	@Autowired
	private LotteryActivityManager lotteryActivityManager;

	@Autowired
	private LotteryPrizeManager lotteryPrizeManager;

	@Autowired
	private LotteryPrizeDetailDao lotteryPrizeDetailDao;

	@Autowired
	private SurveyAnswerDao surveyAnswerDao;

	@Autowired
	private LotteryPrizeArithmeticDao lotteryPrizeArithmeticDao;

	@Override
	public void setBaseDao() {
		this.baseDao = lotteryUserDao;

	}

	@Override
	public LotteryUserDetail initApprovalPage(String lauId, String wxid) {
		//先看看保存过明细信息没有
		List<Criterion> criterions=new ArrayList<Criterion>();
		criterions.add(Restrictions.eq("lotteryUserId", lauId));
		LotteryUserDetail lud = lotteryUserDetailDao.findFirst(criterions);
		if (lud == null) {
			//没有就试图从微信拿信息覆盖过来
			WcUserDetail wcUD = wechatManager.getWcUserDetail(wxid);
			LotteryUserDetail ludNew = new LotteryUserDetail();
			if (wcUD != null) {
				ludNew.setAddress(wcUD.getAddress());
				ludNew.setPhone(wcUD.getPhone());
				ludNew.setZipcode(wcUD.getZipcode());
				ludNew.setName(wcUD.getName());
			}
			ludNew.setLotteryUserId(lauId);
			ludNew.setId(null);
			return ludNew;
		} else {
			return lud;
		}
	}

	@Override
	public LotteryUserDetail getLotteryUserDetail(String id) {
		return lotteryUserDetailDao.get(id);
	}

	@Override
	public void saveLotteryUserDetail(LotteryUserDetail lotteryUserDetail) {
		 lotteryUserDetailDao.save(lotteryUserDetail);

	}

	@Override
	public Map<String, Object> initLotteryPage(String surveyId,String wxid) {
		Map<String,Object> resultMap = new HashMap<String,Object>();
		// step1 构造9宫格，要严格记得顺序
		LotteryActivity la = lotteryActivityManager.getBySurveyId(surveyId);
		LotteryPrize lp = lotteryPrizeManager.getByActivityId(la.getId());
		List<LotteryPrizeDetail> lpdList = lotteryPrizeDetailDao.find(Restrictions.eq("lotteryPrizeId", lp.getId()));
		String[] prizeList = new String[8];
		String[] prizeListLevel = new String[8];
		for (int i = 0; i< lpdList.size(); i++) {
			//前台显示的奖品名要显示描述-----------------------------
            if (i == lpdList.size()) {
                prizeList[i] = lpdList.get(i).getDescription();
            } else {
                if (lpdList.get(i).getDescription().length()>0) {
                    prizeList[i] = lpdList.get(i).getDescription() + "    ";

                } else {
                    prizeList[i] = lpdList.get(i).getDescription();
                }
            }
            System.out.println("prizeList["+i+"] = " + prizeList[i]);
			//prizeListLevel[i] = lpdList.get(i).getDescription() + lpdList.get(i).getValue();
		}
		resultMap.put("prizeList", prizeList);
		//resultMap.put("prizeListLevel", prizeListLevel);
		// step2 找到用户剩余次数
		Long lotteryCount = getUserLotteryedTimes(surveyId,wxid);
		int restCount = (int) (lp.getPartTimes() - lotteryCount);
		resultMap.put("restCount", restCount);
		// step3找到活动开始结束时间
		resultMap.put("time", SystemUtils.dateToStr(la.getStartTime(), "MM-dd") + "-" + SystemUtils.dateToStr(la.getEndTime(), "MM-dd"));
		// step4找到活动规则
		resultMap.put("description", la.getDescription());
		return resultMap;
	}

	@Override
	public Long getUserLotteryedTimes(String surveyId,String wxid) {
		String hql = "select  count(*) from StudentLottery sl where sl.surveyId = ? and sl.wxId = ?";
		return  (Long) studentLotteryDao.findUniObjs(hql, surveyId, wxid);
	}

	@SuppressWarnings({"rawtypes" })
	@Override
	public Map findUserLotterPrize(String answerId,String wxid) {
		SurveyAnswer sa = surveyAnswerDao.get(answerId);
		Map<String,String> dataMap = new HashMap<String,String>();
		Map resultMap = new HashMap<String,String>();
		// 0--成功
		// 1--curNo = totNo 抽满了
		// 2--发生异常锁表了
		// 3--莫名奇妙把次数刷满了

		//获取prize
		LotteryActivity la = lotteryActivityManager.getBySurveyId(sa.getSurveyId());
		LotteryPrize lp = lotteryPrizeManager.getByActivityId(la.getId());

		String surveyAnswerId = sa.getId();

		//以防万一再check一下，看看这小子到没到次数
		Long lotteryCount = getUserLotteryedTimes(sa.getSurveyId(),wxid);
		int restCount = (int) (lp.getPartTimes() - lotteryCount);
		if (restCount <= 0) {
			resultMap = SystemUtils.buildResultMap(3, dataMap, "您剩余抽奖次数为0，不能抽奖~");
			return resultMap;
		}


		//此处针对表t_lottery_prize_status做了一个全表的悲观锁
		//注意,不要用currentSession,要新开一个session
		Session session = lotteryPrizeStatusDao.getSessionFactory().openSession();
		Transaction tx = session.beginTransaction();
		try{
			String hql = "from LotteryPrizeStatus lps where lps.lotteryPrizeId = '"+lp.getId() +"'";
			Query query  =  session.createQuery(hql);
			query.setLockOptions(LockOptions.UPGRADE);
			LotteryPrizeStatus lps = (LotteryPrizeStatus) query.list().get(0);
			int curNo = lps.getCurPrizeNo();
			int tolNo = lps.getTalPrizeNo();
			if (curNo == tolNo) {
				resultMap = SystemUtils.buildResultMap(1, dataMap, "该活动已经结束");
				return resultMap;
			}
			//去算法表寻找奖品类型1-8
			List<Criterion> criterions2=new ArrayList<Criterion>();
			criterions2.add(Restrictions.eq("allocationNo", curNo + 1));
			criterions2.add(Restrictions.eq("lotteryPrizeId", lp.getId()));
			LotteryPrizeArithmetic lpa = lotteryPrizeArithmeticDao.findFirst(criterions2);
			int userPrize = lpa.getAllocationPrizeNo();
			//更新一下status表
			lps.setCurPrizeNo(curNo + 1);
			session.save(lps);
			//提交事务
			tx.commit();
			session.close();

			//增加中奖记录信息
			LotteryUser luNew = new LotteryUser();
			luNew.setId(null);
			luNew.setWxId(wxid);
			luNew.setLotteryTime(new Date());
			luNew.setSurveyAnswerId(surveyAnswerId);
			luNew.setApprovalStatus("1");
			luNew.setArithmeticId(lpa.getId());
			lotteryUserDao.save(luNew);

			dataMap.put("userPrize", String.valueOf(userPrize));
			resultMap = SystemUtils.buildResultMap(0, dataMap, "");
			return resultMap;

		} catch(Exception e) {
			//如果出意外了,防止死锁，直接回退
			resultMap = SystemUtils.buildResultMap(2, dataMap, "服务器繁忙，请稍后再试~");
			e.printStackTrace();
			tx.rollback();
			session.close();
			return resultMap;
		}
	}
}
